package com.superman.supermarket.client.widget.numbereditor;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * 数字编辑器.可加减数字
 * 
 * @author superman
 * @version 2018年8月8日下午3:58:58
 */
public class NumCounter extends Composite implements HasValueChangeHandlers<Map<String, Integer>> {

	interface NumCounterUiBinder extends UiBinder<Widget, NumCounter> {
	}

	/**
	 * 错误回调接口
	 * 
	 * @author superman
	 * @version 2018年8月8日下午3:59:24
	 */
	public interface NumErrorHandler {
		/**
		 * 展示错误
		 * 
		 * @author superman
		 * @version 2018年8月8日 下午3:59:26
		 */
		void showError();
	}

	private static NumCounterUiBinder uiBinder = GWT.create(NumCounterUiBinder.class);

	private int beforeValue = 1;
	private NumErrorHandler errorHandler;
	@UiField
	TextBox input;
	@UiField
	FlowPanel mainpanel;
	private int max;
	private int min = 1;
	@UiField
	Button subbtn, addbtn;

	private int value = 1;

	/**
	 * 构造方法
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午3:59:20
	 */
	public NumCounter() {
		initWidget(uiBinder.createAndBindUi(this));
		subbtn.setHTML("&minus;");
		addbtn.setHTML("&plus;");
		input.setReadOnly(true);
		input.getElement().setAttribute("type", "tel");
	}

	@UiHandler("addbtn")
	void addAddBtnClickHandler(ClickEvent event) {
		event.stopPropagation();
		if (value == max) {
			if (errorHandler != null) {
				errorHandler.showError();
			}
		} else {
			try {
				beforeValue = value;
				setValue(++value);
			} catch (NumCounterOutOfBoundryException e) {
				e.printStackTrace();
			}
		}
	}

	@UiHandler("input")
	void addInputValueChangeHandler(KeyUpEvent event) {
		int intValue = 0;
		try {
			intValue = Integer.parseInt(input.getValue());
		} catch (NumberFormatException e) {
			try {
				beforeValue = value;
				setValue(value);
			} catch (NumCounterOutOfBoundryException e1) {
				e1.printStackTrace();
			}
		}

		if (intValue < min) {
			try {
				setValue(1);
			} catch (NumCounterOutOfBoundryException e) {
				e.printStackTrace();
			}
		} else if (intValue > max) {
			if (errorHandler != null)
				errorHandler.showError();
			try {
				setValue(value);
			} catch (NumCounterOutOfBoundryException e) {
				e.printStackTrace();
			}
		} else {
			try {
				setValue(intValue);
			} catch (NumCounterOutOfBoundryException e) {
				e.printStackTrace();
			}
		}
	}

	@UiHandler("subbtn")
	void addMulBtnClickHandler(ClickEvent event) {
		event.stopPropagation();
		if (value == min) {
			if (errorHandler != null) {
				errorHandler.showError();
			}
		} else {
			try {
				beforeValue = value;
				setValue(--value);
			} catch (NumCounterOutOfBoundryException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Map<String, Integer>> handler) {
		return addHandler(handler, ValueChangeEvent.getType());
	}

	/**
	 * 取值
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午4:00:26
	 * @return value
	 */
	public int getValue() {
		return value;
	}

	/**
	 * 重制
	 * 
	 * @author superman
	 * @version 2018年8月9日 下午5:06:39
	 * @param reset
	 */
	public void reset(int reset) {
		this.value = reset;
		input.setValue(value + "");
	}

	/**
	 * 设置错误处理接口
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午3:59:57
	 * @param errorHandler
	 */
	public void setErrorHandler(NumErrorHandler errorHandler) {
		this.errorHandler = errorHandler;
	}

	/**
	 * 设置最大值
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午4:00:08
	 * @param max
	 */
	public void setMax(int max) {
		this.max = max;
	}

	/**
	 * 设置最小值
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午4:00:11
	 * @param min
	 */
	public void setMin(int min) {
		this.min = min;
	}

	/**
	 * 设置值
	 * 
	 * @author superman
	 * @version 2018年8月8日 下午4:00:39
	 * @param value
	 * @throws NumCounterOutOfBoundryException
	 */
	public void setValue(int value) throws NumCounterOutOfBoundryException {
		// 记录变更前的值
		if (value > max) {
			this.value = max;
			input.setValue(max + "");
			throw new NumCounterOutOfBoundryException();
		} else if (value < min) {
			this.value = min;
			input.setValue(min + "");
			throw new NumCounterOutOfBoundryException();
		} else {
			this.value = value;
			input.setValue(value + "");
		}

		// 当变更后的值和变更前的值不等时,触发事件
		if (this.value != beforeValue) {
			Map<String, Integer> map = new HashMap<String, Integer>();
			map.put("BEFORE", beforeValue);
			map.put("AFTER", this.value);
			ValueChangeEvent.fire(this, map);
		}
	}

}
